package cn.itcast.hotel;

import cn.itcast.hotel.pojo.Hotel;
import cn.itcast.hotel.pojo.HotelDoc;
import cn.itcast.hotel.service.IHotelService;
import com.alibaba.fastjson.JSON;
import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import static cn.itcast.hotel.content.Content.HOTEL_MAPPINGS;

@SpringBootTest
public class test {
    @Autowired
    private IHotelService hotelService;

    private RestHighLevelClient client;

    @BeforeEach
    void setup() {
        this.client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.226.129:9200")
        ));
        //System.out.println("初始化已经完成......");
    }

    @Test
    public void test1() {
        System.out.println(client);
    }

    @Test
    public void test2() throws IOException {
        //创建hotel索引库
        CreateIndexRequest request = new CreateIndexRequest("hotel");
        request.source(HOTEL_MAPPINGS, XContentType.JSON);
        client.indices().create(request, RequestOptions.DEFAULT);
    }

    @Test
    public void test3() throws IOException {
        //获取hotel索引库
        GetIndexRequest request = new GetIndexRequest("hotel");
        boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
        System.out.println(exists);
    }

    @Test
    public void test4() throws IOException {
        //删除hotel索引库
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("hotel");
        client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
    }

    @Test
    public void test5() throws IOException {
        //hotel索引库插入文档
        Hotel hotel = hotelService.getById(38812);
        HotelDoc hotelDoc = new HotelDoc(hotel);

        IndexRequest indexRequest = new IndexRequest("hotel").id(hotelDoc.getId().toString());
        indexRequest.source(JSON.toJSONString(hotelDoc), XContentType.JSON);
        client.index(indexRequest, RequestOptions.DEFAULT);

    }

    @Test
    public void test6() throws IOException {
        //hotel索引库获取文档
        GetRequest getRequest = new GetRequest("hotel", "38812");

        GetResponse response = client.get(getRequest, RequestOptions.DEFAULT);

        String source = response.getSourceAsString();

        HotelDoc hotelDoc = JSON.parseObject(source, HotelDoc.class);

        System.out.println(hotelDoc);
    }

    @Test
    public void test7() throws IOException {
        //hotel索引库修改文档
        UpdateRequest updateRequest = new UpdateRequest("hotel", "38812");

        updateRequest.doc(
                "city", "北京",
                "address", "河南省信阳市息县"
        );

        client.update(updateRequest, RequestOptions.DEFAULT);

    }

    @Test
    public void test8() throws IOException {
        //hotel索引库删除文档
        DeleteRequest deleteRequest = new DeleteRequest("hotel", "38812");

        client.delete(deleteRequest, RequestOptions.DEFAULT);

    }

    @Test
    public void test9() throws IOException {
        //hotel索引库批量插入文档
        BulkRequest bulkRequest = new BulkRequest();

        List<Hotel> list = hotelService.list();

        for (Hotel hotel : list) {
            HotelDoc hotelDoc = new HotelDoc(hotel);

            bulkRequest.add(new IndexRequest("hotel").id(hotelDoc.getId().toString()).source(JSON.toJSONString(hotelDoc), XContentType.JSON));
        }

        client.bulk(bulkRequest, RequestOptions.DEFAULT);

    }

    @Test
    public void test10() throws IOException {
        //hotel索引库查询全部
        SearchRequest searchRequest = new SearchRequest("hotel");

        searchRequest.source().query(QueryBuilders.matchAllQuery());

        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

        getResponseValue(response);

    }

    @Test
    public void test11() throws IOException {
        //hotel索引库单条件查询
        SearchRequest searchRequest = new SearchRequest("hotel");

        searchRequest.source().query(QueryBuilders.matchQuery("all", "如家"));

        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

        getResponseValue(response);

    }

    @Test
    public void test12() throws IOException {
        //hotel索引库多条件组合查询
        SearchRequest searchRequest = new SearchRequest("hotel");

        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        boolQuery.must(QueryBuilders.termQuery("city", "上海"));

        boolQuery.filter(QueryBuilders.rangeQuery("price").gt(200));

        searchRequest.source().query(boolQuery);

        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

        getResponseValue(response);

    }

    @Test
    public void test13() throws IOException {
        //hotel索引库多条件组合查询加排序和分页
        SearchRequest searchRequest = new SearchRequest("hotel");

        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        boolQuery.must(QueryBuilders.termQuery("city", "上海"));

        boolQuery.filter(QueryBuilders.rangeQuery("price").gt(200));

        searchRequest.source().query(boolQuery);

        searchRequest.source().from(0);

        searchRequest.source().size(2);

        searchRequest.source().sort("price", SortOrder.ASC);

        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

        getResponseValue(response);

    }

    @Test
    public void test14() throws IOException {
        //hotel索引库高亮显示
        SearchRequest searchRequest = new SearchRequest("hotel");

        searchRequest.source().query(QueryBuilders.matchQuery("all", "如家"));

        searchRequest.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));

        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();

        for (SearchHit hit : hits) {
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField highlightField = highlightFields.get("name");
            for (Text fragment : highlightField.getFragments()) {
                System.out.println(fragment.toString());
            }
        }

    }

    @Test
    public void test15() throws IOException {
        //hotel索引库聚合
        SearchRequest searchRequest = new SearchRequest("hotel");

        //设置文本大小
        searchRequest.source().size(0);
        //构建聚合函数
        searchRequest.source().aggregation(AggregationBuilders
                //设置聚合查询方式，以及该聚合名称
                .terms("brandAggs")
                //设置聚合字段
                .field("brand"));

        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

        Aggregations aggregations = response.getAggregations();
        //必须用Terms类型进行接受，使用快捷键的类型不对
        Terms brandAggs = aggregations.get("brandAggs");
        List<? extends Terms.Bucket> buckets = brandAggs.getBuckets();
        for (Terms.Bucket bucket : buckets) {
            System.out.println(bucket.getKeyAsString() + " " + bucket.getDocCount());
        }
    }

    @Test
    public void test16() throws IOException {
//        Map<String, List<String>> filter = hotelService.filter();
//        System.out.println(filter);
    }

    @Test
    public void test17() throws IOException {
        //hotel索引库自动补全
        SearchRequest searchRequest = new SearchRequest("hotel");
        //构建自动补全语句
        SuggestBuilder suggestBuilder = new SuggestBuilder().addSuggestion(
                //自定义名称
                "mySuggestion",
                //自动补全的字段
                SuggestBuilders.completionSuggestion("suggestion")
                        //关键字
                        .prefix("s")
                        //跳过重复
                        .skipDuplicates(true)
                        //获取前10条数据
                        .size(10));

        searchRequest.source().suggest(suggestBuilder);

        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        //解析回应
        Suggest suggest = response.getSuggest();

        CompletionSuggestion mySuggestion = suggest.getSuggestion("mySuggestion");

        for (CompletionSuggestion.Entry.Option option : mySuggestion.getOptions()) {
            String text = option.getText().toString();
            System.out.println(text);
        }
    }
    private static void getResponseValue(SearchResponse response) {
        SearchHits hits = response.getHits();

        SearchHit[] hitsHits = hits.getHits();

        for (SearchHit hitsHit : hitsHits) {

            String source = hitsHit.getSourceAsString();

            HotelDoc hotelDoc = JSON.parseObject(source, HotelDoc.class);

            System.out.println(hotelDoc);
        }
    }


    @AfterEach
    void close() throws IOException {
        this.client.close();
        //System.out.println("资源释放已经完成......");
    }
}
